package Dominio.Entidades;

import java.io.Serializable;
import java.util.Arrays;

public class Pieza implements Serializable, Comparable<Pieza> {

    //private boolean esFicha;
    private String ficha;
    private TipoPieza tipo;
    private Coordenada[] ubicacion;

    public Pieza(TipoPieza pTipoLadrillo) {
        this.tipo = pTipoLadrillo;
    }

    public Pieza(TipoPieza pTipoLadrillo, Coordenada[] pUbicacion) {
        this.tipo = pTipoLadrillo;
        this.ubicacion = pUbicacion;
    }

    public Pieza(String pFicha, TipoPieza pTipoLadrillo, Coordenada[] pUbicacion) {
        this.ficha = pFicha;
        this.tipo = pTipoLadrillo;
        this.ubicacion = pUbicacion;
    }

    public String getFicha() {
        return ficha;
    }

    public void setFicha(String pFicha) {
        this.ficha = pFicha;
    }

    public boolean isEsFicha() {
        return (this.getTipo() == TipoPieza.Ficha);
    }

    public TipoPieza getTipo() {
        return tipo;
    }

    public void setTipo(TipoPieza pLadrillo) {
        this.tipo = pLadrillo;
    }

    public Coordenada[] getUbicacion() {
        return ubicacion;
    }

    public void setUbicacion(Coordenada[] pUbicacion) {
        this.ubicacion = pUbicacion;
    }

    private boolean cargarUbicacion(Coordenada[] pCoordenadas) {
        boolean retorno = true;
        if (TipoPieza.Ficha.equals(this.getTipo())) {
            this.setUbicacion(new Coordenada[1]);
            this.getUbicacion()[0] = pCoordenadas[pCoordenadas.length - 2];
        } else {
            this.setUbicacion(pCoordenadas);
        }
        return retorno;
    }

    public void ordenarUbicaciones() {
        Coordenada ultimoOrdenado = null;
        Coordenada[] ordenado = new Coordenada[ubicacion.length];
        for (int i = 0; i < ordenado.length; i++) {
            Coordenada anterior = null;
            for (int o = 0; o < ubicacion.length; o++) {
                Coordenada actual = this.getUbicacion()[o];
                //Si hay un anterior y el anterior es mayor al actual
                //pongo el anterior en la posicion actual y al alcual en el anterior
                if (ultimoOrdenado != null) {
                    if (anterior == null) {
                        if (actual.compareTo(ultimoOrdenado) > 0) {
                            anterior = actual;
                        }
                    } else {
                        if (actual.compareTo(ultimoOrdenado) > 0 && actual.compareTo(anterior) < 0) {
                            anterior = actual;
                        }
                    }
                } else {
                    if (anterior == null) {
                        anterior = actual;
                    } else {
                        if (actual.compareTo(anterior) < 0) {
                            anterior = actual;
                        }
                    }
                }
            }
            ordenado[i] = anterior;
            ultimoOrdenado = anterior;
            anterior = null;
        }
        this.setUbicacion(ordenado);
    }

    public boolean contienePosicion(Coordenada pPosicion) {
        boolean esta = false;
        for (int pos = 0; pos < this.getUbicacion().length && !esta; pos++) {
            Coordenada coordenada = this.getUbicacion()[pos];
            esta = coordenada.equals(pPosicion);
        }
        return esta;
    }

    public boolean movimientosValidos() throws Exception {
        boolean validos = true;
        int cont = 0;
        Coordenada ubicacionAnterior = null;

        //ordenarUbicaciones();
        if (ubicacion.length > 1) {

            for (int i = 0; i < ubicacion.length; i++) {
                Coordenada ubicaccionActual = this.getUbicacion()[i];
                if (ubicacionAnterior == null) {

                    ubicacionAnterior = ubicaccionActual;
                } else {

                    if (!((ubicacionAnterior.getPosFila() == ubicaccionActual.getPosFila()
                            && (ubicacionAnterior.getPosColumna() + 1 == ubicaccionActual.getPosColumna()
                            || ubicacionAnterior.getPosColumna() - 1 == ubicaccionActual.getPosColumna()))
                            || (ubicacionAnterior.getPosColumna() == ubicaccionActual.getPosColumna()
                            && (ubicacionAnterior.getPosFila() + 1 == ubicaccionActual.getPosFila()
                            || ubicacionAnterior.getPosFila() - 1 == ubicaccionActual.getPosFila())))) {
                        for (int j = 0; j < ubicacion.length; j++) {
                            Coordenada ubicacionAlternativa = ubicacion[j];
                            //Si la actual es diferente y la anterior tambien
                            if (!ubicacionAlternativa.equals(ubicacionAnterior) && !ubicacionAlternativa.equals(ubicaccionActual)) {

                                if (!((ubicacionAlternativa.getPosFila() == ubicaccionActual.getPosFila()
                                        && (ubicacionAlternativa.getPosColumna() + 1 == ubicaccionActual.getPosColumna()
                                        || ubicacionAlternativa.getPosColumna() - 1 == ubicaccionActual.getPosColumna()))
                                        || (ubicacionAlternativa.getPosColumna() == ubicaccionActual.getPosColumna()
                                        && (ubicacionAlternativa.getPosFila() + 1 == ubicaccionActual.getPosFila()
                                        || ubicacionAlternativa.getPosFila() - 1 == ubicaccionActual.getPosFila())))) {
                                    throw new Exception("Los movimientos ingresados no generan un ladrillo");
                                }
                            }
                        }

                    } else {
                        ubicacionAnterior = ubicaccionActual;
                    }
                }
            }
        }
        return validos;
    }

    public boolean equals(Pieza other) {
        boolean existe = true;
        if (this.getTipo().equals(other.getTipo())) {
            for (int i = 0; i < this.getUbicacion().length && existe; i++) {
                Coordenada coordenada = this.getUbicacion()[i];
                //Pongo en fale pasa saber si esta en la otra pieza.
                existe = false;
                existe = other.contienePosicion(coordenada);
            }
        }else{
            existe = false;
        }
        return existe;
    }

    @Override
    public int compareTo(Pieza o) {
        int retorno = 0;
        if (this.getTipo() != null) {
            retorno = this.getTipo().compareTo(o.getTipo());
        }
        return retorno;
    }

    @Override
    public Pieza clone() {
        Pieza nueva = new Pieza(tipo);
        nueva.setUbicacion(new Coordenada[getUbicacion().length]);
        for (int i = 0; i < ubicacion.length; i++) {
            Coordenada coordenada = ubicacion[i];
            nueva.getUbicacion()[i] = new Coordenada(coordenada.getPosFila(), coordenada.getPosColumna());
        }
        return nueva;
    }
}
